package cn.edu.zut.mock;

import cn.edu.zut.bean.OrderDetail;
import com.github.javafaker.Faker;

import java.sql.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeUnit;

public class OrderDetailDataGenerator {

    private static final String DB_URL = "jdbc:mysql://hadoop102:3306/driver?allowPublicKeyRetrieval=true&useSSL=false&requireSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "000000";
    private static final int BATCH_SIZE = 100;

    // 缓存 driver_id 避免重复查询
    private static List<String> driverIds = null;

    public static void main(String[] args) {
        // 每次运行追加10条数据
        int count = 10;
        generateData(count);
    }

    public static void generateData(int count) {
        Faker faker = new Faker(Locale.CHINA);
        List<OrderDetail> details = new ArrayList<>();

        if (driverIds == null || driverIds.isEmpty()) {
            driverIds = getAllDriverIds();
        }

        if (driverIds == null || driverIds.isEmpty()) {
            throw new IllegalStateException("driver 表中没有可用的 driver_id");
        }

        // 获取数据库中已有的最大order_id
        long startId = getMaxOrderId() + 1;

        for (long i = startId; i < startId + count; i++) {
            String orderId = String.valueOf(i); // 按照 1, 2, 3... 规则生成 order_id
            String driverId = getRandomDriverId(faker);
            double basePrice = generateRandomBasePrice(faker);
            double mileagePrice = generateRandomMileagePrice(faker);
            double timePrice = generateRandomTimePrice(faker);
            double totalPrice = Math.round((basePrice + mileagePrice + timePrice) * 100.0) / 100.0;

            // 构建订单明细
            OrderDetail detail = OrderDetail.builder()
                    .order_id(orderId)
                    .driver_id(driverId)
                    .pickup_time(generateRandomPickupTime(faker))
                    .pickup_location(faker.address().cityName())
                    .destination(faker.address().cityName())
                    .distance(generateRandomDistance(faker))
                    .order_time(generateRandomTimeInSeconds(faker))
                    .base_price(basePrice)
                    .mileage_price(mileagePrice)
                    .time_price(timePrice)
                    .total_price(totalPrice) // 总价由前三项计算而来
                    .status(generateRandomStatus(faker))
                    .payment_status(mapPaymentStatusFromStatus(generateRandomStatus(faker))) // 关联状态
                    .payment_type(generateRandomPaymentType(faker))
                    .passeger_mark(generateRandomMark(faker))
                    .passenger_comment(generateRandomComment(faker))
                    .build();

            details.add(detail);
        }

        insertIntoDatabase(details);
    }

    private static void insertIntoDatabase(List<OrderDetail> details) {
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
            conn.setAutoCommit(false);
            String sql = "INSERT INTO order_detail (" +
                    "order_id, driver_id, pickup_time, pickup_location, destination, distance, order_time, base_price, mileage_price, time_price, total_price, status, payment_status, payment_type, passeger_mark, passenger_comment" +
                    ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

            try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
                for (int i = 0; i < details.size(); i++) {
                    OrderDetail d = details.get(i);
                    pstmt.setString(1, d.getOrder_id());
                    pstmt.setString(2, d.getDriver_id());
                    pstmt.setTimestamp(3, new Timestamp(d.getPickup_time().getTime()));
                    pstmt.setString(4, d.getPickup_location());
                    pstmt.setString(5, d.getDestination());
                    pstmt.setDouble(6, d.getDistance());
                    pstmt.setInt(7, d.getOrder_time());
                    pstmt.setDouble(8, d.getBase_price());
                    pstmt.setDouble(9, d.getMileage_price());
                    pstmt.setDouble(10, d.getTime_price());
                    pstmt.setDouble(11, d.getTotal_price());
                    pstmt.setInt(12, d.getStatus());
                    pstmt.setInt(13, d.getPayment_status());
                    pstmt.setInt(14, d.getPayment_type());
                    pstmt.setString(15, d.getPasseger_mark());
                    pstmt.setString(16, d.getPassenger_comment());
                    pstmt.addBatch();

                    if ((i + 1) % BATCH_SIZE == 0 || i == details.size() - 1) {
                        pstmt.executeBatch();
                    }
                }
                conn.commit();
                System.out.println("成功插入" + details.size() + "条订单明细信息");
            } catch (SQLException e) {
                conn.rollback();
                e.printStackTrace();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private static String getRandomDriverId(Faker faker) {
        return driverIds.get(faker.random().nextInt(driverIds.size()));
    }

    private static Date generateRandomPickupTime(Faker faker) {
        return new Date(faker.date().past(365, TimeUnit.DAYS).getTime());
    }

    private static double generateRandomDistance(Faker faker) {
        return Math.round(faker.number().randomDouble(2, 1, 30) * 10.0) / 10.0;
    }

    private static int generateRandomTimeInSeconds(Faker faker) {
        return faker.number().numberBetween(300, 7200); // 5分钟~2小时
    }

    private static double generateRandomBasePrice(Faker faker) {
        return Math.round(faker.number().randomDouble(2, 5, 15) * 100.0) / 100.0;
    }

    private static double generateRandomMileagePrice(Faker faker) {
        return Math.round(faker.number().randomDouble(2, 5, 50) * 100.0) / 100.0;
    }

    private static double generateRandomTimePrice(Faker faker) {
        return Math.round(faker.number().randomDouble(2, 0, 20) * 100.0) / 100.0;
    }

    private static int generateRandomStatus(Faker faker) {
        return faker.random().nextInt(0, 3); // 状态：0（未完成）~3（超时）
    }

    private static int mapPaymentStatusFromStatus(int status) {
        switch (status) {
            case 0: return 0; // 未完成 -> 未支付
            case 1: return 1; // 完成 -> 已支付
            case 2:
            case 3: return 2; // 取消/超时 -> 已退款
            default: return 2;
        }
    }

    private static int generateRandomPaymentType(Faker faker) {
        return faker.random().nextInt(1, 3); // 1-微信，2-支付宝，3-银行卡
    }

    private static String generateRandomMark(Faker faker) {
        return String.valueOf(faker.random().nextInt(1, 5));
    }

    private static String generateRandomComment(Faker faker) {
        String[] comments = {
                "服务很好", "司机很专业", "车辆干净", "准时到达", "价格合理",
                "体验一般", "迟到几分钟", "车况不好", "没有沟通好", "下次还会选"
        };
        return comments[faker.random().nextInt(comments.length)];
    }

    /**
     * 查询所有 driver_id
     */
    public static List<String> getAllDriverIds() {
        List<String> ids = new ArrayList<>();
        String query = "SELECT driver_id FROM driver";

        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(query)) {

            while (rs.next()) {
                ids.add(rs.getString("driver_id"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return ids;
    }

    /**
     * 查询数据库中已有的最大order_id
     */
    private static long getMaxOrderId() {
        String sql = "SELECT MAX(CAST(order_id AS SIGNED)) FROM order_detail";
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             PreparedStatement pstmt = conn.prepareStatement(sql);
             ResultSet rs = pstmt.executeQuery()) {
            if (rs.next()) {
                return rs.getLong(1);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return 0; // 如果表为空，返回0
    }
}